// 最终版 vite-plugin-boltron.ts
import { Plugin, PluginOption } from 'vite';
import { Project, Node, Type, ts } from 'ts-morph';
import { globSync } from 'glob';
import path from 'path';
import fs from 'fs';

interface ScanConfig {
  /** 包含 IPC 注册的文件匹配模式 */
  include?: string | string[];
  /** 需要排除的文件模式 */
  exclude?: string | string[];
  /** 最大扫描深度（默认 6） */
  maxDepth?: number;
  /** 是否扫描 node_modules (默认 false) */
  scanNodeModules?: boolean;
}

interface BoltronPluginOptions {
  mainEntry?: string;
  preloadOutput: string;
  typeOutput?: string;
  scan?: ScanConfig;
}

interface IpcMethodInfo {
  params: Array<{ isPromise: boolean; valueType: string }>;
  returnType: { isPromise: boolean; valueType: string };
}

interface IpcNamespaceSchema {
  [methodName: string]: IpcMethodInfo;
}

interface IpcSchema {
  [namespace: string]: IpcNamespaceSchema;
}

// 判断节点是否为IPC注册调用
function isIpcRegistration(node: Node): boolean {
  if (!node.isKind(ts.SyntaxKind.CallExpression)) return false;

  const callExpr = node.asKind(ts.SyntaxKind.CallExpression);
  if (!callExpr) return false;

  const expr = callExpr.getExpression();
  if (!expr.isKind(ts.SyntaxKind.PropertyAccessExpression)) return false;

  const propExpr = expr.asKind(ts.SyntaxKind.PropertyAccessExpression);
  if (!propExpr) return false;

  return propExpr.getName() === 'registerIpcHandler' &&
         callExpr.getArguments().length === 2;
}

// 解析命名空间
function parseNamespace(node: Node): string {
  if (node.isKind(ts.SyntaxKind.StringLiteral)) {
    return node.asKind(ts.SyntaxKind.StringLiteral)?.getLiteralValue() || 'unknown';
  }

  if (node.isKind(ts.SyntaxKind.Identifier)) {
    return node.getText();
  }

  return 'unknown';
}

// 序列化类型为可读格式
function serializeType(typeObj: Type): { isPromise: boolean; valueType: string } {
  const typeString = typeObj.getText();

  // 如果是 Promise 类型，尝试提取泛型参数
  if (typeString.startsWith('Promise<')) {
    return {
      isPromise: true,
      valueType: typeString.substring(8, typeString.length - 1)
    };
  }

  return {
    isPromise: false,
    valueType: typeString
  };
}

// 解析处理方法
function parseHandlerMethods(handlerNode: Node): IpcNamespaceSchema {
  const methods: IpcNamespaceSchema = {};

  if (handlerNode.isKind(ts.SyntaxKind.ObjectLiteralExpression)) {
    const objExpr = handlerNode.asKind(ts.SyntaxKind.ObjectLiteralExpression);
    if (!objExpr) return methods;

    objExpr.getProperties().forEach(prop => {
      if (prop.isKind(ts.SyntaxKind.PropertyAssignment)) {
        const propAssignment = prop.asKind(ts.SyntaxKind.PropertyAssignment);
        if (!propAssignment) return;

        const methodName = propAssignment.getName();
        const initializer = propAssignment.getInitializer();

        if (initializer && initializer.isKind(ts.SyntaxKind.ArrowFunction)) {
          const arrowFunc = initializer.asKind(ts.SyntaxKind.ArrowFunction);

          if (arrowFunc) {
            const returnType = arrowFunc.getReturnType();
            const parameters = arrowFunc.getParameters().map(p => serializeType(p.getType()));

            methods[methodName] = {
              params: parameters,
              returnType: serializeType(returnType)
            };
          }
        }
      }
    });
  }

  return methods;
}

// 生成预加载脚本内容
function generatePreloadContent(ipcSchema: IpcSchema): string {
  let content = `// 自动生成的 Boltron 预加载脚本
// 此文件由 vite-plugin-boltron 自动生成，请勿手动修改
import { contextBridge, ipcRenderer } from 'electron';

// 暴露安全的 API 到渲染进程
contextBridge.exposeInMainWorld('electron', {
  ipc: {
`;

  // 为每个命名空间创建对应的 API
  Object.entries(ipcSchema).forEach(([namespace, methods]) => {
    content += `    ${namespace}: {\n`;

    // 为每个方法创建对应的 API
    Object.keys(methods).forEach(methodName => {
      content += `      ${methodName}: (...args) => ipcRenderer.invoke('${namespace}:${methodName}', ...args),\n`;
    });

    content += `    },\n`;
  });

  content += `  },
});`;

  return content;
}

// 生成类型定义内容
function generateTypeContent(ipcSchema: IpcSchema): string {
  let content = `// 自动生成的 Boltron IPC 类型定义
// 此文件由 vite-plugin-boltron 自动生成，请勿手动修改

/**
 * IPC 主进程 API 类型
 */
export interface BoltronRendererApi {
`;

  // 添加所有 IPC 方法的类型
  Object.entries(ipcSchema).forEach(([namespace, methods]) => {
    Object.entries(methods).forEach(([methodName, methodInfo]) => {
      const params = (methodInfo.params || [])
        .map((param, index) => `arg${index}: ${param.valueType}`)
        .join(', ');

      const returnType = methodInfo.returnType?.isPromise
        ? `Promise<${methodInfo.returnType.valueType}>`
        : `Promise<${methodInfo.returnType?.valueType || 'any'}>`;

      content += `  '${namespace}:${methodName}': (${params}) => ${returnType};\n`;
    });
  });

  content += `}

/**
 * 全局 Window 接口扩展
 */
declare global {
  interface window {
    electron: {
      ipc: BoltronRendererApi
    }
  }
}`;

  return content;
}

export default function boltronPlugin(options: BoltronPluginOptions): PluginOption {
  const defaultConfig: ScanConfig = {
    include: ['**/*.ipc.ts', '**/main/*.ts'],
    exclude: ['**/node_modules/**', '**/dist/**'],
    maxDepth: 6,
    scanNodeModules: false
  };

  // 扫描项目文件
  function scanProjectFiles(): string[] {
    const { include, exclude, maxDepth, scanNodeModules } = options.scan!;

    return globSync(include || ['**/*.ipc.ts'], {
      ignore: exclude,
      nodir: true,
      absolute: true,
      cwd: process.cwd(),
      // @ts-ignore - 类型定义问题，但实际globSync支持depth参数
      depth: maxDepth,
      follow: !scanNodeModules
    }).filter(file => {
      if (!scanNodeModules) {
        return !file.includes('node_modules');
      }
      return true;
    });
  }

  // 分析IPC处理器
  function analyzeIpcHandlers(files: string[]): IpcSchema {
    const project = new Project();
    project.addSourceFilesAtPaths(files);

    const schema: IpcSchema = {};

    project.getSourceFiles().forEach(file => {
      file.forEachDescendant(node => {
        if (isIpcRegistration(node)) {
          const args = node.asKind(ts.SyntaxKind.CallExpression)?.getArguments();
          if (!args || args.length < 2) return;

          const namespaceNode = args[0];
          const handlerNode = args[1];

          const namespace = parseNamespace(namespaceNode);
          const methods = parseHandlerMethods(handlerNode);

          schema[namespace] = {
            ...schema[namespace],
            ...methods
          };
        }
      });
    });

    return schema;
  }

  // 生成预加载脚本
  function generatePreload(ipcSchema: IpcSchema): void {
    const outputPath = path.resolve(process.cwd(), options.preloadOutput);
    const preloadDir = path.dirname(outputPath);

    // 确保目录存在
    if (!fs.existsSync(preloadDir)) {
      fs.mkdirSync(preloadDir, { recursive: true });
    }

    // 生成预加载脚本内容
    const preloadContent = generatePreloadContent(ipcSchema);

    // 写入文件
    fs.writeFileSync(outputPath, preloadContent, 'utf-8');
    console.log(`[boltron] 生成预加载脚本: ${outputPath}`);
  }

  // 生成类型定义文件
  function generateTypes(ipcSchema: IpcSchema): void {
    if (!options.typeOutput) return;

    const outputPath = path.resolve(process.cwd(), options.typeOutput);
    const typeDir = path.dirname(outputPath);

    // 确保目录存在
    if (!fs.existsSync(typeDir)) {
      fs.mkdirSync(typeDir, { recursive: true });
    }

    // 生成类型定义内容
    const typeContent = generateTypeContent(ipcSchema);

    // 写入文件
    fs.writeFileSync(outputPath, typeContent, 'utf-8');
    console.log(`[boltron] 生成类型定义: ${outputPath}`);
  }

  return {
    name: 'vite-plugin-boltron-pro',
    enforce: 'pre',

    // 配置解析
    configResolved(config) {
      options.scan = {
        ...defaultConfig,
        ...options.scan,
        exclude: [
          ...(defaultConfig.exclude as string[]),
          ...(options.scan?.exclude || [])
        ]
      };

      // 设置默认类型输出路径（如果未指定）
      if (!options.typeOutput && options.preloadOutput) {
        options.typeOutput = `${options.preloadOutput.replace(/.js|.mjs/g, '')}.d.ts`;
      }
    },

    // 构建初始化
    async buildStart() {
      const startTime = Date.now();
      const scannedFiles = scanProjectFiles();
      const ipcSchema = analyzeIpcHandlers(scannedFiles);

      // 生成产物
      generatePreload(ipcSchema);
      generateTypes(ipcSchema);

      console.log(`[boltron] 扫描完成，耗时 ${Date.now() - startTime}ms`);
      console.log(`[boltron] 扫描文件数: ${scannedFiles.length}`);
      console.log(`[boltron] 发现 IPC 方法: ${Object.keys(ipcSchema).length}`);
    }
  } as Plugin;
}
